079

您所在的位置:网站首页 条件竞争 测试工具包括 079

079

2024-07-09 00:16| 来源: 网络整理| 查看: 265

大多数时候,我们对并发的直觉都是错误的,特别是在多核处理器上更为明显。这也是高并发程序难写的原因。

人类想了种种办法来降低程序员犯错误的机率,发明了很多方法。甚至在有些语言里,干脆就不支持多线程了,比如基于 NodeJs 开发的服务器。

但在 Golang 里我们无法逃避这种并发竞争。

1. 竞争例子

下面这个例子开启了 100 个 goroutine,读写全局变量 a.

// demo01.go package main import ( "fmt" "sync" ) var a int func run() { a++ } func main() { var wg sync.WaitGroup num := 100 wg.Add(num) for i := 0; i < num; i++ { go func() { run() wg.Done() }() } wg.Wait() fmt.Printf("a = %d\n", a) }

这里写图片描述 图1 运行结果

上面的程序反复运行了几次,发现有几次结果不太一样,我们期望的结果应该是 100。

原因就在于 a++ 这一行语句不是原子执行的。

2. 竞争检测

golang 提供了竞争检测工具,用来辅助我们发现程序种出现的数据竞争。只要在命令后面加上 -race 选项就可以了:

$ go test -race mypkg // 测试包 $ go run -race mysrc.go // 编译和运行程序 $ go build -race mycmd // 构建程序 $ go install -race mypkg // 安装程序

在我们这个例子中,你可以使用下面的方法:

$ go run -race demo01.go

或者你也可以使用

$ go build -race demo01.go $ ./demo01

这里写图片描述 图2 使用竞争检漏工具

竞争检测器集成在go工具链中。当使用了-race作为命令行参数后,编译器会插桩代码,使得所有代码在访问内存时,会记录访问时间和方法。同时运行时库会观察对共享变量的未同步访问。

3. 使用互斥锁解决竞争问题 // demo02.go package main import ( "fmt" "sync" ) var a int var mu sync.Mutex func run() { mu.Lock() defer mu.Unlock() a++ } func main() { var wg sync.WaitGroup num := 100 wg.Add(num) for i := 0; i < num; i++ { go func() { run() wg.Done() }() } wg.Wait() fmt.Printf("a = %d\n", a) }

接下来再运行 go run -race demo02.go,就没有问题了,而且每次结果都是 100.

这里写图片描述 图3 运行结果

4. 总结 学会使用竞争检测工具


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3